package com.matezk.sael.hardware;

import android.util.Log;

import org.json.JSONException;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;

public class GpioControl {
    private static final String FILE_DIRECTION_FORMAT = "/sys/class/gpio/gpio%d/direction";
    private static final String FILE_VALUE_FORMAT = "/sys/class/gpio/gpio%d/value";

    enum Level {
        LOW,
        HIGH
    }

    enum Direction {
        IN,
        OUT
    }

    private static final String TAG = GpioControl.class.getSimpleName();

    private PowerType powerType = PowerType.SD;
    private PowerState powerState = PowerState.OFF;

    private static GpioControl control = new GpioControl();

    public static GpioControl getInstance() {
        return control;
    }



    public enum PowerType implements Serializable {
        SD,
        AQD
    }

    public enum PowerState implements Serializable {
        OFF,
        ON
    }

    public PowerType getPowerType() {
        return powerType;
    }

    public PowerState getPowerState() {
        return powerState;
    }

    public interface PowerStateChangeCallBack {
        void execute(PowerState powerState) throws JSONException;
    }

    public void changePowerState(PowerState powerState, PowerStateChangeCallBack callBack) {
        this.powerState = powerState;
        if (null != callBack) {
            try {
                callBack.execute(this.powerState);
            } catch (JSONException e) {
                Log.d(TAG, "changePowerState", e);
            }
        }
    }

    public void togglePowerState(PowerStateChangeCallBack callBack) {
        if (powerState == PowerState.OFF) {
            this.powerState = PowerState.ON;
        } else {
            this.powerState = PowerState.OFF;
        }
        if (null != callBack) {
            try {
                callBack.execute(this.powerState);
            } catch (JSONException e) {
                Log.d(TAG, "togglePowerState", e);
            }
        }
    }

    public interface PowerTypeChangeCallBack {
        void execute(PowerType powerType) throws JSONException;
    }

    public void changePowerType(PowerType powerType, PowerTypeChangeCallBack callBack) {
        this.powerType = powerType;
        if (null != callBack) {
            try {
                callBack.execute(this.powerType);
            } catch (JSONException e) {
                Log.d(TAG, "changePowerType", e);
            }
        }
    }

    public void togglePowerType(PowerTypeChangeCallBack callBack) {
        if (powerType == PowerType.SD) {
            this.powerType = PowerType.AQD;
        } else {
            this.powerType = PowerType.SD;
        }
        if (null != callBack) {
            try {
                callBack.execute(this.powerType);
            } catch (JSONException e) {
                Log.d(TAG, "togglePowerType", e);
            }
        }
    }

    // 设置GPIO输入输出
    public void setGpioDirection(int gpio, Direction direction) throws IOException {
        writeGpio(String.format(FILE_DIRECTION_FORMAT, gpio), Direction.IN == direction ? "in" : "out");
    }

    // 设置GPIO输出电平
    public void setGpio(int gpio, Level level) {
        writeGpio(String.format(FILE_VALUE_FORMAT, gpio), String.valueOf(level.ordinal()));
    }

    // 读取GPIO电平
    public int readGpio(int gpio) {
        String text = readGpio(String.format(FILE_VALUE_FORMAT, gpio));
        return null == text || text.isEmpty() ? 0 : Integer.valueOf(text);
    }

    // 写GPIO文件
    private void writeGpio(String gpio, String value) {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(gpio);
            out.write(value.getBytes());
        } catch (Exception e) {

        } finally {
            try {
                out.close();
            } catch (Exception e) {}
        }
    }

    // 读GPIO文件
    private String readGpio(String gpio) {
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(gpio);
            byte bytes[] = new byte[3];
            fin.read(bytes);
            return new String(bytes);
        } catch (IOException e) {
            try {
                fin.close();
            } catch (IOException ioException) {
            }
        }
        return null;
    }
}
